/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/graphics/dx11.1/details/dxtex_helper.hpp>
#include <baja/graphics/dx11.1/details/common.hpp>

// directx specific utilities
// this file is pretty much a big hack
// and this should go into baja::graphics but for now i am just leaving it here as a set of backdoors into dx
namespace baja { namespace graphics { namespace dx11_1 {

namespace b = baja;
namespace g = baja::graphics;
namespace gd = baja::graphics::dx11_1::details;

inline const std::vector<const b::memory>& createSolidBlendState()
{
    static std::vector<const b::memory> s_returnValue;

    if (s_returnValue.size() == 0)
    {
        s_returnValue.resize(sizeof(D3D11_BLEND_DESC));

        D3D11_BLEND_DESC* desc =  reinterpret_cast<D3D11_BLEND_DESC*>(s_returnValue.data());

        std::memset(desc, 0, sizeof(D3D11_BLEND_DESC));
        desc->AlphaToCoverageEnable = false;
        desc->IndependentBlendEnable = false;
        desc->RenderTarget[0].BlendEnable = false;
        desc->RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
        desc->RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
        desc->RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    }

    return s_returnValue;
}

inline std::vector<const b::memory>& createAlphaBlendState(bool enableAll = true)
{
    static std::vector<const b::memory> s_returnValue;
    static std::vector<const b::memory> s_returnValueEnableAll;

    std::vector<const b::memory>& vec = enableAll ? s_returnValueEnableAll : s_returnValue;

    if (vec.size() == 0)
    {
        vec.resize(sizeof(D3D11_BLEND_DESC));

        D3D11_BLEND_DESC* desc = reinterpret_cast<D3D11_BLEND_DESC*>(vec.data());

        std::memset(desc, 0, sizeof(D3D11_BLEND_DESC));

        desc->AlphaToCoverageEnable = false;
        desc->IndependentBlendEnable = false;
        desc->RenderTarget[0].BlendEnable = true;
        desc->RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
        desc->RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
        desc->RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
        desc->RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
        desc->RenderTarget[0].BlendOpAlpha= D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].RenderTargetWriteMask = enableAll ? D3D11_COLOR_WRITE_ENABLE_ALL : (D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE);
    }

    return vec;
}

inline std::vector<const b::memory>& createLassoBlendState()
{
    static std::vector<const b::memory> s_returnValue;
    std::vector<const b::memory>& vec = s_returnValue;

    if (vec.size() == 0)
    {
        vec.resize(sizeof(D3D11_BLEND_DESC));

        D3D11_BLEND_DESC* desc = reinterpret_cast<D3D11_BLEND_DESC*>(vec.data());

        std::memset(desc, 0, sizeof(D3D11_BLEND_DESC));

        desc->AlphaToCoverageEnable = false;
        desc->IndependentBlendEnable = false;
        desc->RenderTarget[0].BlendEnable = true;
        desc->RenderTarget[0].SrcBlend = D3D11_BLEND_INV_DEST_COLOR;
        desc->RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC1_COLOR;
        desc->RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
        desc->RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
        desc->RenderTarget[0].BlendOpAlpha= D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
    }

    return vec;
}

inline std::vector<const b::memory>& createHighlighterBlendState()
{
    static std::vector<const b::memory> s_returnValue;

    if (s_returnValue.size() == 0)
    {
        s_returnValue.resize(sizeof(D3D11_BLEND_DESC));

        D3D11_BLEND_DESC* desc = reinterpret_cast<D3D11_BLEND_DESC*>(s_returnValue.data());

        std::memset(desc, 0, sizeof(D3D11_BLEND_DESC));

        desc->AlphaToCoverageEnable = false;
        desc->IndependentBlendEnable = false;
        desc->RenderTarget[0].BlendEnable = true;
        desc->RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
        desc->RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
        desc->RenderTarget[0].BlendOp = D3D11_BLEND_OP_MIN;
        desc->RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
        desc->RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
        desc->RenderTarget[0].BlendOpAlpha= D3D11_BLEND_OP_ADD;
        desc->RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
    }
    
    return s_returnValue;
}

}}} // namespace baja::graphics::d3d11_1